/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/
/**
 * \file
 * \brief HubCtrl Protocol datatype definitions header.
 * \author Antti Maula <antti.maula@tkk.fi>
 */
#ifndef _HUBCTRLHDR_H_
#define _HUBCTRLHDR_H_
#include "protocolID.h"
#include <inttypes.h>

// Protocol identification
#define HUBCTRLPROTOCOL_NUMBER                   0x00
#define HUBCTRLPROTOCOL_VERSION                  0x02

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
//////////////////  HubCtrl - Request numbers /////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

typedef enum EnumHubCtrlRequest {
  
  /** Undefined request.
   *
   * This is a value which is used to distinct correct elements from
   * spurious ones. It should never be sent to GIMnet under any
   * circumstanses. Receiving or sending a request of this type always
   * indicates an error.
   */
  KHubCtrlRequestUndefined                     = 0x00,

  /** Request local link NodeId.
   * This Request returns a NodeId packed inside a
   * THubCtrlSubHeaderNodeInfo subheader container.
   * Required elements:
   * - Base header
   * Replied with:
   * - Base header
   * - KHubCtrlSubtypeNodeInfo
   */
  KHubCtrlRequestQueryLocalNodeId              = 0x01,

  /** Request Client echo.
   * This request is sent by access point to client.
   * Client must respond to this request as fast as possible,
   * as it is used 
   * Required elements:
   * - Base header
   * - KHubCtrlSubtypeTimestamp
   * Replied with:
   * - Base header
   * - KHubCtrlSubtypeTimestamp (Original sent by server)
   */
  KHubCtrlRequestClientEcho                    = 0x02,
  
  /** Server side ECHO.
   * This is request type which is sent from client to server.  The
   * GIMnetAP will always respond as fast as possible.
   * Required elements:
   * - Base header
   * Replied with:
   * - Base header
   * - KHubCtrlSubtypeTimestamp (Original sent by client)
   */
  KHubCtrlRequestServerEcho                    = 0x03,
  
  /** Request version information from AccessPoint.
   * This command requests AP to respond with its own
   * version information.
   * Required elements:
   * - Base header
   * Replied with:
   * - Base header
   * - KHubCtrlSubtypeVersion
   */
  KHubCtrlRequestHubVersion                    = 0x04,

  /** Register AccessPoint.
   *
   * This command is required for setting up a H2H link. 
   * This message is sent to the Hub the current node is 
   * connecting to. 
   * Required elements:
   * - Base header
   * - KHubCtrlSubtypeRegisterAP
   * - KHubCtrlSubtypeAuthentication
   * Replied with:
   * - Base header
   * - KHubCtrlSubtypeRegisterAP [on success]
   * - KHubCtrlSubtypeAuthentication (server authenticates its own reply) [on success]
   */
  KHubCtrlRequestRegisterAP                    = 0x05,
  

  /** Register an access point service.
   *
   * This command is intended for register GIMnetAP Services. Purpose
   * of this command is to provide mechanism which allows connecting
   * clients to reassign a "fixed" address for themselves. This is
   * required in order to provide pre-known addresses for services
   * such as NameService.
   *
   * Required elements:
   * - Base header
   * - KHubCtrlSubtypeRegisterAPService
   * - KHubCtrlSubtypeAuthentication
   * Replied with:
   * - Base header
   * - KHubCtrlSubtypeRegisterAPService [on success]
   * - KHubCtrlSubtypeAuthentication (server authenticates its own reply) [on success]
   */
  KHubCtrlRequestRegisterAPService             = 0x06,


  /** Register an access point Client.
   *
   * This command is used for registering an AccessPoint Client.  In
   * current version of GIMnet, EVERY client must be authenticated
   * before communicating with other nodes in the
   * system. Authentication key may be left to default value, which
   * allows creating "Open" access points.
   *
   * Required elements:
   * - Base header
   * - KHubCtrlSubtypeAuthentication
   * Replied with:
   * - Base header
   * - KHubCtrlSubtypeAuthentication (server authenticates its own reply) [on success]
   */
  KHubCtrlRequestRegisterAPClient              = 0x07,


  /** Request contents of node routing table.
   *
   * \note This query requires authenticated H2H or Service status.
   *
   */
  KHubCtrlRequestRoutingGetTable               = 0x08,


  /** Add new Routing table entry.
   *
   * \note This query requires authenticated H2H or Service status.
   */
  KHubCtrlRequestRoutingAddEntry               = 0x09,
  

  /** Delete existing Routing table entry.
   *
   * \note This query requires authenticated H2H or Service status.
   */
  KHubCtrlRequestRoutingDeleteEntry            = 0x0a,
  

  /** Upload a table to remote AP for routing table merge.
   *
   * \note This query requires authenticated H2H or Service status.
   */
  KHubCtrlRequestRoutingUpdateTable            = 0x0b,


  /** Create a new H2H link.
   *
   * \note This query requires authenticated H2H or Service status.
   */
  KHubCtrlRequestAP2APCreateLink                 = 0x0c,
  

  /** Delete existing H2H link.
   *
   * \note This query requires authenticated H2H or Service status.
   */
  KHubCtrlRequestAP2APDeleteLink                 = 0x0d,
  

  /** Get existing H2H links.
   *
   * \note This query requires authenticated H2H or Service status.
   */
  KHubCtrlRequestAP2APGetLinks                   = 0x0e

  
} EHubCtrlRequest;
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
//////////////////  HubCtrl - Flags ///////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

/** HubCtrl flags.
 * 
 */
typedef enum EnumHubCtrlFlag{
  KHubCtrlFlagReply                            = (1<<0) ///< Packet is a reply to previous query
} EHubCtrlFlag;
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
////////////////// HubCtrl - Sub Headers  /////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

enum EnumHubCtrlSubtype{
  KHubCtrlSubtypeAuthentication                = 0x01, ///< See THubCtrlSubHeaderAuthentication
  KHubCtrlSubtypeVersion                       = 0x02, ///< See THubCtrlSubHeaderVersion
  KHubCtrlSubtypeRegisterAP                    = 0x03, ///< See THubCtrlSubHeaderRegisterAP
  KHubCtrlSubtypeNodeInfo                      = 0x04, ///< See THubCtrlSubHeaderNodeInfo
  KHubCtrlSubtypeRegisterAPService             = 0x05, ///< See THubCtrlSubHeaderRegisterAPService
  KHubCtrlSubtypeTimestamp                     = 0x06  ///< See THubCtrlSubHeaderTimestamp
};

///////////////////////////////////////////////////////////////////////////////


/** Base structure for reading the identification info.  Has the same
 * structure as subheaders, although they also contain the same
 * fields.
 */
typedef struct SHubCtrlSubHeaderIdentificationHeader
{
  unsigned subtype : 8;           ///< Type of SubHeader
  unsigned subsize : 24;          ///< Size of SubHeader (To support iterating headers)
} THubCtrlSubHeaderIdentificationHeader;

/** Authentication
 *
 */
typedef struct SHubCtrlSubHeaderAuthentication
{
  unsigned subtype : 8;           ///< KHubCtrlSubtypeAuthentication
  unsigned subsize : 24;          ///< sizeof(THubCtrlSubHeaderAuthentication)
  uint8_t sha1[20];               ///< 20 * 8 bits == 160bits == SHA-1 size
  uint32_t timestamp_s;           ///< Timestamp in seconds when auth was made.
} THubCtrlSubHeaderAuthentication;


/** AP Version
 *
 */
typedef struct SHubCtrlSubHeaderVersion
{
  unsigned subtype : 8;           ///< KHubCtrlSubtypeVersion
  unsigned subsize : 24;          ///< sizeof(THubCtrlSubHeaderAuthentication) 
  uint8_t major;                  ///< Major version.
  uint8_t minor;                  ///< Minor version.
  uint8_t sub;                    ///< Sub version (if 0, not printed)
  uint8_t fix;                    ///< Fix version (if 0, not printed)
  uint16_t build;                 ///< Build number
  uint16_t protocol_ver;          ///< Protocol version
} THubCtrlSubHeaderVersion;


/** Register Access Point
 *
 */
typedef struct SHubCtrlSubHeaderRegisterAP
{
  unsigned subtype : 8;           ///< KHubCtrlSubtypeRegisterAP
  unsigned subsize : 24;          ///< sizeof(THubCtrlSubHeaderRegisterAP)
  uint32_t peer_id;               ///< Peer Identifier.
} THubCtrlSubHeaderRegisterAP;


/** Timestamp
 *
 */
typedef struct SHubCtrlSubHeaderTimestamp
{
  unsigned subtype : 8;           ///< KHubCtrlSubtypeTimestamp
  unsigned subsize : 24;          ///< sizeof(THubCtrlSubHeaderTimestamp)
  uint32_t seconds;
  uint32_t useconds;
} THubCtrlSubHeaderTimestamp;


/** Node information subheader.
 *
 */
typedef struct SHubCtrlSubHeaderNodeInfo
{
  unsigned subtype : 8;           ///< KHubCtrlSubtypeNodeInfo
  unsigned subsize : 24;          ///< sizeof(THubCtrlSubHeaderNodeInfo)
  uint32_t nodeid;                ///< FQ nodeid
  uint32_t link_delay_us;         ///< Link delay in microseconds (max is approx. 1.19h)
} THubCtrlSubHeaderNodeInfo;


/** Register Access Point Service
 *
 */
typedef struct SHubCtrlSubHeaderRegisterAPService
{
  unsigned subtype : 8;           ///< KHubCtrlSubtypeRegisterAPService
  unsigned subsize : 24;          ///< sizeof(THubCtrlSubHeaderRegisterAPService)
  uint32_t requested_id;          ///< Requested ID in FQ format (high 16 bits ignored)
  uint32_t service_type;          ///< Service type ID. (May be enforced by Hub)
  
} THubCtrlSubHeaderRegisterAPService;

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
////////////////// HubCtrl - MainHeader ///////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
typedef enum EnumHubCtrlResult {
  KHubCtrlResultOK            = 0x00, ///< Operation was OK.
  KHubCtrlResultAuthExpired   = 0x01, ///< Authorization failed due to expiration (try again)
  KHubCtrlResultAuthFailed    = 0x02, ///< Authorization failed due to invalid credentials
  KHubCtrlResultIdReserved    = 0x03, ///< Requested operation tried to reserve already reserved id.
  KHubCtrlResultUnknownError  = 0xff  ///< Operation yielded on unknown error
} EHubCtrlResult;

/** HubCtrl protocol main header.
 * 
 */
typedef struct SHubCtrlProtocolHeader
{
  TProtocolIdentification protocol_id;   ///< Compulsory protocol_id struct (4)
 
  uint8_t request;             ///< Type of request 
  uint8_t subheader_count;     ///< Number of subheaders
  uint8_t flags;               ///< Flags
  uint8_t result;              ///< Operation result code (0 == OK)

  uint32_t message_id;         ///< Request identifier, used for binding req/replies together.

} THubCtrlProtocolHeader;

#endif


